"""Chinese text cleaning utilities for ASR outputs.

- Collapses excessive whitespace and normalizes punctuation.
- Removes common non-text noise such as emojis and control characters.
- Returns simplified, clean text suitable for downstream classification.

Note: Does not convert Traditional to Simplified Chinese. If needed,
consider integrating OpenCC at a later stage behind a config flag.
"""
from __future__ import annotations

import re
from typing import Optional

__all__ = ["clean_zh_text"]

# Regex covering most emoji and symbols outside basic punctuation/letters/numbers
_EMOJI_NOISE_RE = re.compile(
    r"[\U0001F300-\U0001F64F\U0001F680-\U0001F6FF\U0001F700-\U0001F77F\U0001F780-\U0001F7FF\U0001F800-\U0001F8FF\U0001F900-\U0001F9FF\U0001FA00-\U0001FA6F\U0001FA70-\U0001FAFF]"
)

# Map common ASCII punctuation to Chinese variants
_ASCII_TO_CN_PUNCT = {
    ",": "，",
    ";": "；",
    ":": "：",
    "?": "？",
    "!": "！",
}

# Collapse duplicated Chinese punctuation
_DUP_PUNCT_RE = re.compile(r"([，。！？；、])\1+")

# Normalize runs of dots to a single Chinese period
_DOTS_RE = re.compile(r"\.{2,}")

# Collapse whitespace
_WS_RE = re.compile(r"\s+")


def _ascii_to_cn_punct(s: str) -> str:
    return "".join(_ASCII_TO_CN_PUNCT.get(ch, ch) for ch in s)


def clean_zh_text(text: Optional[str]) -> str:
    """Clean Chinese text for ASR pipeline.

    Steps:
    - Guard None -> "".
    - Remove emojis and non-text noise.
    - Convert common ASCII punctuation to Chinese punctuation.
    - Collapse repeated punctuation (，。！？；、).
    - Normalize runs of dots to a single Chinese period (。).
    - Collapse whitespace to single spaces and strip.
    """
    if not text:
        return ""

    s = str(text)
    # Remove emojis/noise
    s = _EMOJI_NOISE_RE.sub("", s)
    # Convert ASCII punct to CN variants
    s = _ascii_to_cn_punct(s)
    # Normalize dots
    s = _DOTS_RE.sub("。", s)
    # Collapse duplicate CN punctuation
    s = _DUP_PUNCT_RE.sub(r"\1", s)
    # Collapse whitespace
    s = _WS_RE.sub(" ", s).strip()
    return s
